#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <sys/wait.h>
#include <time.h>
#include <signal.h>
#include <string.h>
#include <arpa/inet.h>

#define MAX_CHILDREN 100
#define PORT 8080

struct shm_data {
    struct timespec start_time[MAX_CHILDREN];
    struct timespec end_time[MAX_CHILDREN];
    long total_time; // 总消耗时间（毫秒）
    int child_count; // 子进程数量
};

// 共享内存 & 信号量变量
int shm_id, sem_id;
struct shm_data *shm_ptr;

// 信号量操作函数
void sem_lock(int sem_id) {
    struct sembuf sops = {0, -1, 0};
    semop(sem_id, &sops, 1);
}

void sem_unlock(int sem_id) {
    struct sembuf sops = {0, 1, 0};
    semop(sem_id, &sops, 1);
}

// 信号处理函数
void handle_sigchld(int sig) {
    int status;
    pid_t pid;
    FILE *log_file;

    while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
        if (WIFEXITED(status)) {
            // 打开日志文件
            log_file = fopen("log.txt", "a");
            if (log_file == NULL) {
                perror("Failed to open log file");
                return;
            }

            // 获取共享内存
            shm_ptr = (struct shm_data*)shmat(shm_id, NULL, 0);
            if (shm_ptr == (struct shm_data *)-1) {
                perror("Failed to attach shared memory");
                fclose(log_file);
                return;
            }

            // 查找子进程的索引
            int index = -1;
            for (int i = 0; i < shm_ptr->child_count; i++) {
                if (shm_ptr->start_time[i].tv_sec != 0) {
                    index = i;
                    break;
                }
            }
            if (index == -1) {
                fprintf(stderr, "Child process not found in shared memory\n");
                shmdt(shm_ptr);
                fclose(log_file);
                return;
            }

            // 计算子进程的运行时间
            long child_time = (shm_ptr->end_time[index].tv_sec - shm_ptr->start_time[index].tv_sec) * 1000 +
                              (shm_ptr->end_time[index].tv_nsec - shm_ptr->start_time[index].tv_nsec) / 1000000;

            // 更新总时间
            sem_lock(sem_id);
            shm_ptr->total_time += child_time;
            sem_unlock(sem_id);

            // 写入日志
            fprintf(log_file, "Child %d exited with status %d. Time: %ld ms\n", pid, WEXITSTATUS(status), child_time);
            fprintf(log_file, "Total time: %ld ms\n", shm_ptr->total_time);

            // 释放共享内存
            shmdt(shm_ptr);

            fclose(log_file);
        }
    }
}

int main() {
    int server_socket, client_socket;
    struct sockaddr_in server_addr, client_addr;
    socklen_t client_len = sizeof(client_addr);
    pid_t pid;

    // 创建共享内存
    shm_id = shmget(IPC_PRIVATE, sizeof(struct shm_data), 0666 | IPC_CREAT);
    if (shm_id == -1) {
        perror("Failed to create shared memory");
        exit(EXIT_FAILURE);
    }

    // 创建信号量
    sem_id = semget(IPC_PRIVATE, 1, 0666 | IPC_CREAT);
    if (sem_id == -1) {
        perror("Failed to create semaphore");
        exit(EXIT_FAILURE);
    }

    // 初始化信号量
    semctl(sem_id, 0, SETVAL, 1);

    // 捕获SIGCHLD信号
    signal(SIGCHLD, handle_sigchld);

    // 创建套接字
    server_socket = socket(AF_INET, SOCK_STREAM, 0);
    if (server_socket < 0) {
        perror("Socket creation failed");
        exit(EXIT_FAILURE);
    }

    // 设置服务器地址
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = INADDR_ANY;
    server_addr.sin_port = htons(PORT);

    // 绑定套接字
    if (bind(server_socket, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
        perror("Bind failed");
        close(server_socket);
        exit(EXIT_FAILURE);
    }

    // 开始监听
    if (listen(server_socket, 5) < 0) {
        perror("Listen failed");
        close(server_socket);
        exit(EXIT_FAILURE);
    }

    printf("Server is running on port %d...\n", PORT);

    while (1) {
        // 接受客户端连接
        client_socket = accept(server_socket, (struct sockaddr*)&client_addr, &client_len);
        if (client_socket < 0) {
            perror("Accept failed");
            continue;
        }

        // 创建子进程处理客户端请求
        pid = fork();
        if (pid < 0) {
            perror("Fork failed");
            close(client_socket);
            continue;
        } else if (pid == 0) {
            // 子进程
            close(server_socket); // 子进程不需要监听套接字

            // 获取共享内存
            shm_ptr = (struct shm_data*)shmat(shm_id, NULL, 0);
            if (shm_ptr == (struct shm_data *)-1) {
                perror("Failed to attach shared memory");
                exit(EXIT_FAILURE);
            }

            // 查找子进程的索引
            int index = shm_ptr->child_count;
            sem_lock(sem_id);
            shm_ptr->child_count++;
            sem_unlock(sem_id);

            // 记录起始时间
            clock_gettime(CLOCK_MONOTONIC, &shm_ptr->start_time[index]);

            // 处理客户端请求
            char request[1024];
            int n = read(client_socket, request, sizeof(request) - 1);
            if (n > 0) {
                request[n] = '\0';
                printf("Client request: %s\n", request);

                // 发送简单的HTTP响应
                char response[] = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<html><body><h1>Hello, World!</h1></body></html>";
                write(client_socket, response, strlen(response));
            }

            // 记录结束时间
            clock_gettime(CLOCK_MONOTONIC, &shm_ptr->end_time[index]);

            // 释放共享内存
            shmdt(shm_ptr);

            close(client_socket);
            exit(0);
        } else {
            // 父进程
            close(client_socket); // 父进程关闭客户端套接字
        }
    }

    // 关闭服务器套接字
    close(server_socket);

    // 删除共享内存和信号量
    shmctl(shm_id, IPC_RMID, 0);
    semctl(sem_id, 0, IPC_RMID);

    return 0;
}